package composants
{

	import flash.display.Graphics;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	
	import mx.controls.Alert;
	import mx.core.BitmapAsset;
	import mx.core.UIComponent;
	
	import tools.*;

	/**
	 * Classe qui représente les murs d'une salle
	 */
	public class Mur extends UIComponent
	{
		/**
		 * Variable qui définit un mur
		 * @default mur
		 */
		private var typeMur:String="mur";
		/**
		 *
		 * abscisse du point 1 du mur sur la grille
		 */
		public var x1:int;
		/**
		 *
		 * ordonnée du point 1 du mur sur la grille
		 */
		public var y1:int;
		/**
		 *
		 * abscisse du point 2 du mur sur la grille
		 */
		public var x2:int;
		/**
		 *
		 * ordonnée du point 2 du mur sur la grille
		 */
		public var y2:int;
		/**
		 *
		 * pour identifier à quel mur apprtient une ouverture(portes, fenêtres ou oeuvres)
		 */
		public var idMur:int;
		/**
		 *
		 * @default 0
		 */
		public var offset_x_mur_double:int=0;
		/**
		 *
		 * @default 0
		 */
		public var offset_y_mur_double:int=0;

		// Lors du survol d'un mur par la souris, une icône figurant une ouverture apparaitra (trait jaune)
		// Le bitmap correspondant est directement associé au code :
		[Embed(source="icons/ouverture.png")]
		private var classeIconeOuverture:Class;
		private var iconeOuverture:BitmapAsset;

		// si l'utilisateur clique, cette icône ser remplacée par celle correspondant à l'ouverture effectivement choisie
		// (porte, fenêtre, porte-fenêtre...)
		// Cette opération est effectuée dans GridRoom::ajoutOuverture


		/**
		 * Constructeur : création d'un mur
						  gestion de pré-placement d'une ouverture sur celui-ci
		 * @param px1 abscisse du point 1 du mur
		 * @param py1 ordonnée du point 1 du mur
		 * @param px2 abscisse du point 2 du mur
		 * @param py2 ordonnée du point 2 du mur
		 * @param id identifiant du mur
		 */
		public function Mur(px1:int, py1:int, px2:int, py2:int, id:int)
		{
			x1=px1;
			x2=px2;
			y1=py1;
			y2=py2;
			graphics.lineStyle(5, 0x000000, 1);
			graphics.moveTo(px1, py1);
			graphics.lineTo(px2, py2);
			drawNormal(graphics);
			
			//Ligne transparente pour faciliter le mouseOver
			/*graphics.lineStyle(5, 0x0000FF, 0);
			graphics.moveTo(px1 + 4, py1 + 4);
			graphics.lineTo(px2 + 4, py2 + 4);
			graphics.lineStyle(5, 0x0000FF, 0);
			graphics.moveTo(px1 - 4, py1 - 4);
			graphics.lineTo(px2 - 4, py2 - 4);*/

			addEventListener(MouseEvent.MOUSE_WHEEL, moletteSurUnMurPourChangerNormal);
			this.idMur=id; //permet d'identifier le mur, et ainsi toutes les ouvertures qui lui sont associées 

			// Pour faire apparaître le bitmap générique d'une ouverture
			iconeOuverture=new classeIconeOuverture();
			addChild(iconeOuverture);
			iconeOuverture.visible=false;
			// Calcul des distances des barycentres avec leurs projections sur les faces

			// par rapport à la face nord
			var dis_face_nord:Number=Math.abs(Math.sqrt(Math.pow(0, 2) + Math.pow(Math.abs((py1 + py2) / 2) - 0, 2)));

			// par rapport à la face est
			var dis_face_est:Number=Math.abs(Math.sqrt(Math.pow(Math.abs((px1 + px2) / 2) - 600, 2) + Math.pow(0, 2)));

			// par rapport à la face sud
			var dis_face_sud:Number=Math.abs(Math.sqrt(Math.pow(0, 2) + Math.pow(Math.abs((py1 + py2) / 2) - 600, 2)));

			// par rapport à la face ouest
			var dis_face_ouest:Number=Math.abs(Math.sqrt(Math.pow(Math.abs((px1 + px2) / 2) - 0, 2) + Math.pow(0, 2)));

			var distance_min:Number=Math.min(dis_face_nord, dis_face_est, dis_face_sud, dis_face_ouest);


			// Détection du mur le plus proche (voir parallèle)
			if (dis_face_nord == distance_min)
			{ //Alert.show("Mur proche ou parallèle à la face Nord"); 
				offset_x_mur_double=0;
				offset_y_mur_double=-2;
			}
			else if (dis_face_est == distance_min)
			{ //Alert.show("Mur proche ou parallèle à la face Est");
				offset_x_mur_double=-2;
				offset_y_mur_double=0;
			}
			else if (dis_face_sud == distance_min)
			{ //Alert.show("Mur proche ou parallèle à la face Sud");
				offset_x_mur_double=0;
				offset_y_mur_double=2;
			}
			else
			{ //Alert.show("Mur proche ou parallèle à la face Ouest");
				offset_x_mur_double=2;
				offset_y_mur_double=0;
			}
		}


		/**
		 * Mise en place d'un écouteur sur chaque mur pour la pose d'une porte, d'une oeuvre ou d'une fenêtre
		 * @param ouverture chaine de caractere
		 * @see composants.GridRoom#selectionBouton()
		 */
		public function ajoutListenerOuverture(ouverture:String):void
		{
			//iconeOuverture.scaleX=(GridRoom)(this.parent).getProp();
			//iconeOuverture.scaleY=(GridRoom)(this.parent).getProp();
			addEventListener(MouseEvent.MOUSE_OVER, apparitionOuvertureSurUnMur);
			addEventListener(MouseEvent.MOUSE_OUT, disparitionOuvertureSurUnMur);
			addEventListener(MouseEvent.CLICK, clicSurUnMurPourPlacerUneOuverture);
			
		}



		/**
		 * Fonction qui permet de rectifier les coordonnées des points d'une ouverture pour que cette dernière soit
		 * bien placé sur le mur
		 * @param point1_x_mur abscisse du point 1 du mur
		 * @param point1_y_mur ordonnée du point 1 du mur
		 * @param point2_x_mur abscisse du point 2 du mur
		 * @param point2_y_mur ordonnée du point 2 du mur
		 * @param point_ouverture_x abscisse du point de l'ouverture
		 * @param point_ouverture_y ordonnée du point de l'ouverture
		 * @return un tableau avec les bonnes coordonnées
		 * @private
		 */
		public function calculRotation(point1_x_mur:*, point1_y_mur:*, point2_x_mur:*, point2_y_mur:*, point_ouverture_x:*, point_ouverture_y:*):Array
		{
			var resultat:Array=new Array;
			//On calcul les deux distance entre les points du mur et de l'ouverture
			var distPointOuverture:Number=Geometry.distance(point1_x_mur, point1_y_mur, point_ouverture_x, point_ouverture_y);
			var distPointOuverture1:Number=Geometry.distance(point2_x_mur, point2_y_mur, point_ouverture_x, point_ouverture_y);
			var distPointMur:Number=Geometry.distance(point2_x_mur, point2_y_mur, point1_x_mur, point1_y_mur);
			trace(distPointMur, distPointOuverture1, distPointOuverture);

			//On fait le calcul avec la plus petite (pour eviter que le point sorte de la droite)
			if (distPointOuverture > distPointOuverture1)
			{
				//On calcul le vecteur du mur
				var vecteur_pointMur:Array=Geometry.coordonneVecteur(point2_x_mur, point2_y_mur, point1_x_mur, point1_y_mur);
				//On le normalise
				var vecteur_pointMurNorm:Array=new Array;
				vecteur_pointMurNorm[0]=vecteur_pointMur[0] / distPointMur;
				vecteur_pointMurNorm[1]=vecteur_pointMur[1] / distPointMur;

				//On calcul le vecteur entre l'ouverture et le point du mur
				var vecteur_pointOuverture:Array=Geometry.coordonneVecteur(point_ouverture_x, point_ouverture_y, point1_x_mur, point1_y_mur);
				//On le normalise
				var vecteur_pointOuvertureNorm:Array=new Array;
				vecteur_pointOuvertureNorm[0]=vecteur_pointOuverture[0] / distPointOuverture;
				vecteur_pointOuvertureNorm[1]=vecteur_pointOuverture[1] / distPointOuverture;

				//On fait le produit scalaire
				var rotation:*=(vecteur_pointOuvertureNorm[0] * vecteur_pointMurNorm[0]) + (vecteur_pointOuvertureNorm[1] * vecteur_pointMurNorm[1]);
				var angle:*=Math.acos(rotation);

				//Et enfin on calcul les deux nouveaux points
				resultat[0]=Math.cos(angle) * (point_ouverture_x - point1_x_mur) - Math.sin(angle) * (point_ouverture_y - point1_y_mur) + point1_x_mur;
				resultat[1]=Math.sin(angle) * (point_ouverture_x - point1_x_mur) + Math.cos(angle) * (point_ouverture_y - point1_y_mur) + point1_y_mur;
				trace(resultat);
			}
			else
			{
				//On calcul le vecteur du mur
				var vecteur_pointMur:Array=Geometry.coordonneVecteur(point1_x_mur, point1_y_mur, point2_x_mur, point2_y_mur);
				//On le normalise
				var vecteur_pointMurNorm:Array=new Array;
				vecteur_pointMurNorm[0]=vecteur_pointMur[0] / distPointMur;
				vecteur_pointMurNorm[1]=vecteur_pointMur[1] / distPointMur;
				trace(vecteur_pointMur);
				trace(vecteur_pointMurNorm);
				//On calcul le vecteur entre la porte et le point du mur
				var vecteur_pointOuverture:Array=Geometry.coordonneVecteur(point_ouverture_x, point_ouverture_y, point2_x_mur, point2_y_mur);
				//On le normalise
				var vecteur_pointOuvertureNorm:Array=new Array;
				vecteur_pointOuvertureNorm[0]=vecteur_pointOuverture[0] / distPointOuverture1;
				vecteur_pointOuvertureNorm[1]=vecteur_pointOuverture[1] / distPointOuverture1;
				trace(vecteur_pointOuvertureNorm);
				//On fait le produit scalaire
				trace(vecteur_pointOuvertureNorm[0] * vecteur_pointMurNorm[0], vecteur_pointOuvertureNorm[1] * vecteur_pointMurNorm[1]);
				var rotation:Number=(vecteur_pointOuvertureNorm[0] * vecteur_pointMurNorm[0]) + (vecteur_pointOuvertureNorm[1] * vecteur_pointMurNorm[1]);
				var angle:*=Math.acos(rotation);
				trace(rotation);
				trace(angle);
				//Et enfin on calcul les deux nouveua point

				resultat[0]=Math.cos(angle) * (point_ouverture_x - point2_x_mur) - Math.sin(angle) * (point_ouverture_y - point2_y_mur) + point2_x_mur;
				resultat[1]=Math.sin(angle) * (point_ouverture_x - point2_x_mur) + Math.cos(angle) * (point_ouverture_y - point2_y_mur) + point2_y_mur;
				trace(resultat[0], resultat[1]);
			}
			return resultat;
		}


		/**
		 * Apparition d'une ouverture (icône générique) sur un mur
		 * @param evt évènement souris
		 */
		public function apparitionOuvertureSurUnMur(evt:MouseEvent):void
		{
			/*On récupère les coordonneés de l'ouverture via la souris:
			iconeOuverture.x=evt.localX;
			iconeOuverture.y=evt.localY;*/

			iconeOuverture.rotation=(-Math.atan(((x1 - x2) / (y1 - y2))) / Math.PI * 180 + 90);
			//iconeOuverture.scaleX=(GridRoom)(this.parent).getProp();
			//iconeOuverture.scaleY=(GridRoom)(this.parent).getProp();
			iconeOuverture.visible=true;

			//En fonction de la rotation, on affecte les coordonnées
			var orientation:Number=iconeOuverture.rotation;

			if (orientation == 0 || orientation == 180 || orientation == 360 || orientation == -180 || orientation == -360)
			{
				iconeOuverture.y=this.y1;
				iconeOuverture.x=evt.localX;
			}
			else if (orientation == 90 || orientation == 270 || orientation == -90 || orientation == -270)
			{
				iconeOuverture.x=this.x1;
				iconeOuverture.y=evt.localY;
			}
			else
			{
				iconeOuverture.x=evt.localX;
				iconeOuverture.y=evt.localY;

			}
		}


		/**
		 * L'utilisateur clique sur le mur : l'ouverture est placée
		 * @param event évènement souris
		 */
		public function clicSurUnMurPourPlacerUneOuverture(event:MouseEvent):void
		{
			/*On rectifie les coordonnées de l'ouverture:
			var coordonneesOuverture:Array=new Array;
			coordonneesOuverture=calculRotation(this.x1,this.y1,this.x2,this.y2,iconeOuverture.x,iconeOuverture.y);

			//Enfin on met à jour les coordonées:
			iconeOuverture.x=coordonneesOuverture[1];
			iconeOuverture.y=coordonneesOuverture[0];*/

			typeMur="ouverture";
			(GridRoom)(this.parent).ajoutOuverture(iconeOuverture.x, iconeOuverture.y, iconeOuverture.rotation, x1 + y1 + x2);
		}

		
		/**
		 * L'utilisateur double clique sur le mur : l'ouverture la normal est changé
		 * @param event évènement souris
		 */
		public function moletteSurUnMurPourChangerNormal(event:MouseEvent):void
		{
			var tempX1:* = this.x1;
			var tempY1:* = this.y1;
			this.x1 = this.x2;
			this.y1 = this.y2;
			this.x2 = tempX1;
			this.y2 = tempY1;
			graphics.clear();
			graphics.lineStyle(5, 0x000000, 1);
			graphics.moveTo(x1, y1);
			graphics.lineTo(x2, y2);
			drawNormal(graphics);
			event.stopImmediatePropagation();
			event.stopPropagation();
		}
		
		/**
		 * Suppression des écouteurs sur chaque mur
		 */
		public function removeListenerOuverture():void
		{
			removeEventListener(MouseEvent.MOUSE_OVER, apparitionOuvertureSurUnMur);
			removeEventListener(MouseEvent.CLICK, clicSurUnMurPourPlacerUneOuverture);
			
		}


		/**
		 * Désaffiche l'image de l'ouverture sur le mur
		 * @param event évènement souris
		 */
		public function disparitionOuvertureSurUnMur(event:MouseEvent):void
		{
			iconeOuverture.visible=false;
		}


		//--------------------------------------------------------------------------------------
		// Sauvegarde pseudo-xml du mur

		/**
		 * Cette fonction participe à la création du fichier xml d'une salle.
		 * @param taille
		 * @return du xml sous forme d'un chaine de caractère, contenant les coordonées du mur
		 * @see composants.GridRoom#ecrireFichier()
		 */
		public function toXml(taille:int):String
		{

			var grid:GridRoom=(GridRoom)(parent);
			var pasSize:uint=grid.pasSize;
			var chaine:String="";

			// On écrit les coordonnées du mur en XML et les stocke dans chaine
			chaine="<Vertix x=\"" + (100 * x1 / pasSize).valueOf() + "\" y=\"" + (Math.abs((100 * y1 / pasSize) - taille)).valueOf() + "\" />" + "<Vertix x=\"" + (100 * x2 / pasSize).valueOf() + "\" y=\"" + (Math.abs((100 * y2 / pasSize) - taille)).valueOf() + "\" />";

			return chaine;
		}


		/**
		 * Appelée à partir de GridRoom
		 * @param px abscisse de point
		 * @param py ordonnée de point
		 * @return vrai si les paramètres sont retrouvés dans les coordonnées de l'un des points du mur, sinon faux
		 * @see composants.GridRoom#doubleClicSurLaGrille()
		 */
		public function contientPoint(px:int, py:int):Boolean
		{
			if (x1 == px && y1 == py)
				return true;
			if (x2 == px && y2 == py)
				return true;
			return false;
		}
		
		public function drawNormal( graphics:Graphics ) : void {
			var wallVect:Array = Geometry.coordonneVecteur(x2,y2,x1,y1);
			var dist:* = Geometry.distance(x1,y1,x2,y2);
			wallVect[0]=wallVect[0]/dist;
			wallVect[1]=wallVect[1]/dist;
			var myNormal:Array = Geometry.calculNormal(x2,y2,x1,y1);
			
			
			var P2:Array = new Array( x2 + ( wallVect[0] * 20 ) ,  y2 + ( wallVect[1] * 20 )  );
			
			graphics.beginFill(0xFF0000);
			graphics.moveTo( x2, y2 );
			
			graphics.lineTo( x2 + ( myNormal[0]* 20 ) + ( wallVect[0] * 10 ) , y2 + ( myNormal[1] * 20 )+ (wallVect[1] * 10 ) );
			
			graphics.lineTo( P2[0], P2[1] );
			
			graphics.lineTo(x2, y2 );
			
		}
	}
}